home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Examples / Split-Screen Scrolling / Split-Screen Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  15.3 KB  |  531 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Split-Screen Demo.c
  3. //
  4. // By Vern Jensen. Created 3/8/97
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWFPSReport.h>
  9. #include <SWIncludes.h>
  10. #include <SWGameUtils.h>
  11. #include "SWApplication.h"
  12. #include "Multi-Screen Scrolling.h"
  13.  
  14. #include "Split-Screen Demo.h"
  15. #include "Sprite Stuff.h"
  16.  
  17.  
  18. #define    kInterlacedMode                false        // Skips every other line if on.
  19. #define kSyncToVBL                    false        // Sync SpriteWorld to VBL?
  20. #define kMaxFPS                        30            // Set to 0 for unrestricted speed
  21. #define kLavaFrameRate                7            // Change lava tile every X frames
  22.  
  23. #define kMaxWidth                    800            // max window width
  24. #define kMaxHeight                    600            // max window height
  25.  
  26.  
  27. /***********/
  28. /* Globals */
  29. /***********/
  30.  
  31. WindowPtr            gWindowP;
  32. SpriteWorldPtr        gMasterSpriteWorldP, gCloneSpriteWorldP;
  33. SpriteLayerPtr        gTankSpriteLayerP, gBulletSpriteLayerP, gPowerUpSpriteLayerP;
  34. TileMapStructPtr    gTileMapStructP;
  35. TileMapPtr            gTileMap;
  36. Rect                gMasterRect, gCloneRect;    // The world rects for each SpriteWorld
  37. Rect                gMoveBoundsRect;
  38. DrawProcPtr            gSpriteMaskDrawProc;
  39. RgnHandle            gTempRgn;                    // Used by TankHitDrawProc
  40.  
  41. KeyStruct            gTank1Keys, gTank2Keys;        // Structures containing keys for each tank
  42.  
  43.  
  44.  
  45.  
  46. ///--------------------------------------------------------------------------------------
  47. // Main
  48. ///--------------------------------------------------------------------------------------
  49.  
  50. void    main( void )
  51. {
  52.     Initialize(kNumberOfMoreMastersCalls);
  53.     
  54.     if (SWHasSystem7())
  55.     {
  56.         gTempRgn = NewRgn();    // Create temp region
  57.         AllowKeyUpEvents();        // Part of SWGameUtils.c
  58.         SetCursor(*GetCursor(watchCursor));
  59.         HideControlStrip();
  60.         
  61.         SWSetCleanUpFunction(MyCleanUpFunction);
  62.         
  63.         CreateSpriteWorlds();
  64.         LoadSprites();
  65.         CreateTankSprites();
  66.         
  67.         SetCursor(&qd.arrow);
  68.         HideCursor();
  69.         
  70.         SetUpAnimation();
  71.         RunAnimation();
  72.         ShutDown();
  73.         
  74.         DisposeRgn(gTempRgn);    // Dispose temp region
  75.         RestoreControlStrip();    // Call this after using HideControlStrip before quitting
  76.         RestoreEventMask();        // Call this after using AllowKeyUpEvents before quitting
  77.     }
  78.     else
  79.     {
  80.         CantRunOnThisMachine();
  81.     }
  82. }
  83.  
  84.  
  85. ///--------------------------------------------------------------------------------------
  86. // CreateSpriteWorlds
  87. ///--------------------------------------------------------------------------------------
  88.  
  89. void    CreateSpriteWorlds( void )
  90. {
  91.     Rect        offscreenRect, windRect;
  92.     OSErr        err;
  93.     
  94.     gWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  95.     
  96.     if (gWindowP != NULL)
  97.     {
  98.             // Calculate the size of the window
  99.         windRect.top = 0;
  100.         windRect.left = 0;
  101.         windRect.right = qd.screenBits.bounds.right - 20;
  102.         windRect.bottom = qd.screenBits.bounds.bottom / 1.5;
  103.         
  104.         windRect.right = SW_MIN(windRect.right, kMaxWidth);
  105.         windRect.bottom = SW_MIN(windRect.bottom, kMaxHeight);
  106.         
  107.             // Calculate the rects for each SpriteWorld
  108.         gMasterRect = gCloneRect = windRect;
  109.         gMasterRect.right = gMasterRect.right/2 - 15;
  110.         gCloneRect.left = gMasterRect.right + 30;
  111.         
  112.             // Center the window in the screen
  113.         SizeWindow(gWindowP, windRect.right, windRect.bottom, false);
  114.         CenterRect(&windRect, &qd.screenBits.bounds);
  115.         MoveWindow(gWindowP, windRect.left, windRect.top, false);
  116.         
  117.         ShowWindow(gWindowP);
  118.         SetPort(gWindowP);
  119.     }
  120.     else
  121.         CantFindResource();
  122.     
  123.     
  124.     err = SWEnterSpriteWorld();
  125.     FatalError(err);
  126.     
  127.     
  128.         // Set size of offscreen area
  129.     offscreenRect = gMasterRect;
  130.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  131.     
  132.  
  133.         // Make offscreen area evenly divisible by tile width & height
  134.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  135.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  136.     
  137.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  138.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  139.  
  140.     
  141.         // Create the Master SpriteWorld
  142.     err = SWCreateSpriteWorldFromWindow(&gMasterSpriteWorldP, (CWindowPtr)gWindowP, 
  143.             &gMasterRect, &offscreenRect, 0);
  144.     FatalError(err);
  145.     
  146.         // Create the Clone SpriteWorld
  147.     err = SWCreateSpriteWorldFromWindow(&gCloneSpriteWorldP, (CWindowPtr)gWindowP, 
  148.             &gCloneRect, &offscreenRect, 0);
  149.     FatalError(err);
  150.     
  151.     
  152.         // Init Tiling for the Master SpriteWorld
  153.     err = SWInitTiling(gMasterSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  154.     FatalError(err);
  155.     
  156.         // Init Tiling for the Clone SpriteWorld
  157.     err = SWInitTilingForDuplicateSpriteWorld(gCloneSpriteWorldP, kTileHeight, kTileWidth);
  158.     FatalError(err);
  159.     
  160.     
  161.     err = SWLoadTileMap('TMAP', &gTileMapStructP, 128);
  162.     FatalError(err);
  163.     
  164.     SWInstallTileMap(gMasterSpriteWorldP, gTileMapStructP, 0);
  165.     gTileMap = gTileMapStructP->tileMap;
  166.     
  167.     
  168.         // Load wall tiles
  169.     err = SWLoadTilesFromPictResource(
  170.         gMasterSpriteWorldP, 
  171.         kFirstWallTile,            // startTileID 
  172.         kLastWallTile,            // endTileID
  173.         200,                    // pictResID
  174.         0,                        // maskResID
  175.         kNoMask,                // maskType
  176.         kMaskIsNotPartialMask,    // partialMask?
  177.         0,                        // horizBorderWidth
  178.         0);                        // vertBorderHeight
  179.     FatalError(err);
  180.     
  181.         // Load floor tiles
  182.     err = SWLoadTilesFromPictResource(
  183.         gMasterSpriteWorldP, 
  184.         kFirstFloorTile,        // startTileID 
  185.         kMudTile,                // endTileID
  186.         201,                    // pictResID
  187.         0,                        // maskResID
  188.         kNoMask,                // maskType
  189.         kMaskIsNotPartialMask,    // partialMask?
  190.         0,                        // horizBorderWidth
  191.         0);                        // vertBorderHeight
  192.     FatalError(err);
  193.     
  194.         // Load lava tiles
  195.     err = SWLoadTilesFromPictResource(
  196.         gMasterSpriteWorldP, 
  197.         kFirstLavaTile,            // startTileID 
  198.         kLastLavaTile,            // endTileID
  199.         202,                    // pictResID
  200.         0,                        // maskResID
  201.         kNoMask,                // maskType
  202.         kMaskIsNotPartialMask,    // partialMask?
  203.         0,                        // horizBorderWidth
  204.         0);                        // vertBorderHeight
  205.     FatalError(err);
  206.  
  207.         // Create the sprite layers
  208.     err = SWCreateSpriteLayer(&gPowerUpSpriteLayerP);
  209.     FatalError(err);
  210.     err = SWCreateSpriteLayer(&gBulletSpriteLayerP);
  211.     FatalError(err);
  212.     err = SWCreateSpriteLayer(&gTankSpriteLayerP);
  213.     FatalError(err);
  214.     
  215.         // Add them to the Master SpriteWorld
  216.     SWAddSpriteLayer(gMasterSpriteWorldP, gPowerUpSpriteLayerP);    // Bottom layer
  217.     SWAddSpriteLayer(gMasterSpriteWorldP, gBulletSpriteLayerP);        // Middle layer
  218.     SWAddSpriteLayer(gMasterSpriteWorldP, gTankSpriteLayerP);        // Top layer
  219.     
  220.         // Lock both SpriteWorlds
  221.     SWLockSpriteWorld(gMasterSpriteWorldP);
  222.     SWLockSpriteWorld(gCloneSpriteWorldP);
  223.     
  224.         // Set the gSpriteMaskDrawProc before loading sprites
  225.     if ( SW_PPC )
  226.     {
  227.         if (gMasterSpriteWorldP->pixelDepth >= 8)
  228.             gSpriteMaskDrawProc = BlitPixieMaskDrawProc;
  229.         else
  230.             gSpriteMaskDrawProc = SWStdSpriteDrawProc;
  231.     }
  232.     else
  233.     {
  234.         if (gMasterSpriteWorldP->pixelDepth >= 8)
  235.             gSpriteMaskDrawProc = BlitPixieCompiledSpriteDrawProc;
  236.         else
  237.             gSpriteMaskDrawProc = BlitPixieAllBitMaskDrawProc;
  238.     }
  239.     
  240.     SetRect(&gMoveBoundsRect, 0,0, 
  241.         gMasterSpriteWorldP->tileLayerArray[0]->numCols * kTileWidth,
  242.         gMasterSpriteWorldP->tileLayerArray[0]->numRows * kTileHeight);
  243.     SWSetScrollingWorldMoveBounds(gMasterSpriteWorldP, &gMoveBoundsRect);
  244. }
  245.  
  246.  
  247. ///--------------------------------------------------------------------------------------
  248. // CreateTankSprites
  249. ///--------------------------------------------------------------------------------------
  250.  
  251. void    CreateTankSprites( void )
  252. {
  253.     SpritePtr        mySpriteP;
  254.     TankStructPtr    tankStructP;
  255.     
  256.         // Create the sprite on the left
  257.     mySpriteP = NewTankSprite(kPlayer1);
  258.     tankStructP = (TankStructPtr)mySpriteP;
  259.     
  260.     SWSetSpriteLocation(mySpriteP, gMoveBoundsRect.left + 120, gMoveBoundsRect.top + 100);
  261.     SWSetScrollingWorldMoveProc(gMasterSpriteWorldP, ScrollingWorldMoveProc, mySpriteP);
  262.     
  263.         // Create the sprite on the right
  264.     mySpriteP = NewTankSprite(kPlayer2);
  265.     tankStructP = (TankStructPtr)mySpriteP;
  266.     
  267.     SWSetSpriteLocation(mySpriteP, gMoveBoundsRect.right-140, gMoveBoundsRect.bottom-140);
  268.     SWSetScrollingWorldMoveProc(gCloneSpriteWorldP, ScrollingWorldMoveProc, mySpriteP);
  269.     
  270.         // Create the power-up sprites
  271.     mySpriteP = NewPowerUpSprite(kMachineGun);
  272.     SWSetSpriteLocation(mySpriteP, gMoveBoundsRect.right - 140, gMoveBoundsRect.top + 120);
  273.  
  274.     mySpriteP = NewPowerUpSprite(kMachineGun);
  275.     SWSetSpriteLocation(mySpriteP, gMoveBoundsRect.left + 130, gMoveBoundsRect.bottom - 160);
  276. }
  277.  
  278.  
  279. ///--------------------------------------------------------------------------------------
  280. // SetUpAnimation
  281. ///--------------------------------------------------------------------------------------
  282.  
  283. void    SetUpAnimation( void )
  284. {
  285.     SWSetSpriteWorldMaxFPS(gMasterSpriteWorldP, kMaxFPS);
  286.     SWSyncSpriteWorldToVBL(gMasterSpriteWorldP, kSyncToVBL);
  287.     SWSetCleanUpSpriteWorld(gMasterSpriteWorldP);
  288.     
  289.     SWSetTileChangeProc(gMasterSpriteWorldP, TileChangeProc);
  290.     
  291.         // Move visScrollRect to starting sprite position
  292.     SWMoveVisScrollRect(gMasterSpriteWorldP, 
  293.         gMasterSpriteWorldP->followSpriteP->destFrameRect.left - gMasterSpriteWorldP->backRect.right/2,
  294.         gMasterSpriteWorldP->followSpriteP->destFrameRect.top - gMasterSpriteWorldP->backRect.bottom/2);
  295.     
  296.     
  297.         // Set the various DrawProcs
  298.     if (gMasterSpriteWorldP->pixelDepth >= 8)    // 8-bit, 16-bit, and 32-bit blitter
  299.     {
  300.         SWSetSpriteWorldScreenDrawProc(gMasterSpriteWorldP, BlitPixieRectDrawProc);
  301.         SWSetSpriteWorldOffscreenDrawProc(gMasterSpriteWorldP, BlitPixieRectDrawProc);
  302.         SWSetDoubleRectDrawProc(gMasterSpriteWorldP, BlitPixieDoubleRectDrawProc);
  303.     }
  304.     else if ( SW_68K )        // Use AllBit Blitter when in depths lower than 8-bits on 68k.
  305.     {
  306.         SWSetSpriteWorldOffscreenDrawProc(gMasterSpriteWorldP, BlitPixieAllBitRectDrawProc);
  307.         SWSetSpriteWorldScreenDrawProc(gMasterSpriteWorldP, BlitPixieAllBitRectDrawProc);
  308.     }
  309.     
  310.     if (kInterlacedMode)
  311.     {
  312.         SWSetFrameInterlacingMode(gMasterSpriteWorldP->workFrameP, true, kSkipOddLines);
  313.         SWSetFrameInterlacingMode(gMasterSpriteWorldP->windowFrameP, true, kSkipOddLines);
  314.     }
  315.     
  316.         // Make sure CopyBits, if used, doesn't try to colorize things
  317.     SWSetPortToWindow(gMasterSpriteWorldP);
  318.     ForeColor(blackColor);
  319.     BackColor(whiteColor);
  320.     
  321.         // Copy information from the Master SpriteWorld to the Clone SpriteWorld
  322.     SWSetUpDuplicateSpriteWorld(gMasterSpriteWorldP, gCloneSpriteWorldP);
  323.     
  324.     
  325.     SWDrawTilesInBackground(gMasterSpriteWorldP);
  326.     SWDrawTilesInBackground(gCloneSpriteWorldP);
  327.     SWUpdateScrollingSpriteWorld(gMasterSpriteWorldP, true);
  328.     SWUpdateScrollingSpriteWorld(gCloneSpriteWorldP, true);
  329. }
  330.  
  331.  
  332. ///--------------------------------------------------------------------------------------
  333. //  RunAnimation
  334. ///--------------------------------------------------------------------------------------
  335.  
  336. void    RunAnimation( void )
  337. {
  338.     unsigned long        frames;
  339.     
  340.     frames = 0;
  341.     StartTimer();
  342.     
  343.     FatalError( SWStickyError() );    // Make sure no errors got past us during setup
  344.     
  345.     while (!Button())
  346.     {
  347.         UpdateKeys();
  348.         SWProcessSpriteWorld(gMasterSpriteWorldP);
  349.         
  350.         if (gMasterSpriteWorldP->frameHasOccurred)
  351.         {
  352.             SWProcessMultiScreenSpriteWorld(gMasterSpriteWorldP);
  353.             SWProcessMultiScreenSpriteWorld(gCloneSpriteWorldP);
  354.             SWFinishProcessingMultiScreenSW(gMasterSpriteWorldP);
  355.             
  356.             SWCollideSpriteLayer(gMasterSpriteWorldP, gBulletSpriteLayerP, gTankSpriteLayerP);
  357.             SWCollideSpriteLayer(gMasterSpriteWorldP, gPowerUpSpriteLayerP, gTankSpriteLayerP);
  358.             
  359.                 // Make sure no errors occurred during a MoveProc, etc.
  360.             FatalError( SWStickyError() );
  361.             
  362.             SWAnimateMultiScreenSpriteWorld(gMasterSpriteWorldP);
  363.             SWAnimateMultiScreenSpriteWorld(gCloneSpriteWorldP);
  364.             SWFinishMultiScreenAnimation(gMasterSpriteWorldP);
  365.             
  366.             frames++;
  367.         }
  368.     }
  369.     
  370.     ShowResults(frames);
  371. }
  372.  
  373.  
  374. ///--------------------------------------------------------------------------------------
  375. //  ShutDown (clean up and dispose of the SpriteWorlds)
  376. ///--------------------------------------------------------------------------------------
  377.  
  378. void    ShutDown( void )
  379. {
  380.     SWDisposeDuplicateSpriteWorld(gCloneSpriteWorldP);
  381.     SWDisposeSpriteWorld(&gMasterSpriteWorldP);
  382.     SWExitSpriteWorld();
  383.     
  384.     FlushEvents(everyEvent, 0);
  385.     InitCursor();
  386. }
  387.  
  388.  
  389. ///--------------------------------------------------------------------------------------
  390. //  MyCleanUpFunction - called if an error occurs, to clean up before quitting
  391. ///--------------------------------------------------------------------------------------
  392.  
  393. void    MyCleanUpFunction( void )
  394. {
  395.     RestoreControlStrip();
  396.     RestoreEventMask();    
  397. }
  398.  
  399.  
  400. ///--------------------------------------------------------------------------------------
  401. //  TileChangeProc
  402. ///--------------------------------------------------------------------------------------
  403.  
  404. SW_FUNC void TileChangeProc(
  405.     SpriteWorldPtr spriteWorldP)
  406. {
  407.     short            curImage;
  408.     static short    wallDelay = 0, oldTicks = 0;
  409.     static short    direction = 1;
  410.     short            ticksPassed, ticks;
  411.     
  412.         // Initialize oldTicks the first time this function is called
  413.     if (oldTicks == 0)
  414.         oldTicks = TickCount();
  415.     
  416.     ticks = TickCount();
  417.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  418.     oldTicks = ticks;
  419.     
  420.         // kWallTile
  421.     wallDelay += ticksPassed;
  422.     if (wallDelay >= kLavaFrameRate)
  423.     {
  424.         curImage = spriteWorldP->curTileImage[kFirstLavaTile];
  425.         
  426.             // Cycling mode
  427.         if (curImage < kLastLavaTile)
  428.             curImage++;
  429.         else
  430.         {
  431.             curImage = kFirstLavaTile;
  432.         }
  433.     
  434.         
  435. /*            // Patrolling mode
  436.         if (curImage == kLastLavaTile && direction > 0)
  437.             direction = -1;
  438.         else if (curImage == kFirstLavaTile && direction < 0)
  439.             direction = 1;
  440.         
  441.         curImage += direction;
  442. */        
  443.         
  444.         SWChangeTileImage(gMasterSpriteWorldP, kFirstLavaTile, curImage);
  445.         SWChangeTileImage(gCloneSpriteWorldP, kFirstLavaTile, curImage);
  446.         wallDelay = 0;
  447.     }
  448. }
  449.  
  450.  
  451. ///--------------------------------------------------------------------------------------
  452. //  ScrollingWorldMoveProc
  453. ///--------------------------------------------------------------------------------------
  454.  
  455. SW_FUNC void ScrollingWorldMoveProc(
  456.     SpriteWorldPtr spriteWorldP,
  457.     SpritePtr followSpriteP)
  458. {    
  459.     short    screenWidth, screenHeight, spriteWidth, spriteHeight;
  460.     short    horizPos, vertPos;
  461.     
  462.     screenWidth = (spriteWorldP->visScrollRect.right - spriteWorldP->visScrollRect.left);
  463.     screenHeight = (spriteWorldP->visScrollRect.bottom - spriteWorldP->visScrollRect.top);
  464.     spriteWidth = (followSpriteP->destFrameRect.right - followSpriteP->destFrameRect.left);
  465.     spriteHeight = (followSpriteP->destFrameRect.bottom - followSpriteP->destFrameRect.top);
  466.     
  467.     horizPos = SWGetSpriteHorizLoc(followSpriteP) + spriteWidth/2 - screenWidth/2;
  468.     vertPos = SWGetSpriteVertLoc(followSpriteP) + spriteHeight/2 - screenHeight/2;
  469.     
  470.     if (kInterlacedMode)
  471.         vertPos = vertPos>>1<<1;
  472.     
  473.     SWMoveVisScrollRect(spriteWorldP, horizPos, vertPos);
  474. }
  475.  
  476.  
  477. ///--------------------------------------------------------------------------------------
  478. //  UpdateKeys (Put the latest key values in the gKeys structure)
  479. ///--------------------------------------------------------------------------------------
  480.  
  481. void    UpdateKeys( void )
  482. {
  483.     EventRecord        event;
  484.     short            theKey;
  485.     Boolean            isDown;
  486.     
  487.     while ( GetOSEvent( (keyUpMask | keyDownMask), &event ) )
  488.     {
  489.         theKey = (event.message & keyCodeMask) >> 8;
  490.         isDown = (event.what != keyUp);
  491.         
  492.         switch (theKey)
  493.         {
  494.                 // Tank 1 keys
  495.             case kLeftPlayer1Key:
  496.                 gTank1Keys.left = isDown;
  497.                 break;
  498.             case kRightPlayer1Key:
  499.                 gTank1Keys.right = isDown;
  500.                 break;
  501.             case kDownPlayer1Key:
  502.                 gTank1Keys.down = isDown;
  503.                 break;
  504.             case kUpPlayer1Key:
  505.                 gTank1Keys.up = isDown;
  506.                 break;
  507.             case kShootPlayer1Key:
  508.                 gTank1Keys.shoot = isDown;
  509.                 break;
  510.             
  511.                 // Tank 2 keys
  512.             case kLeftKeyPad:
  513.                 gTank2Keys.left = isDown;
  514.                 break;
  515.             case kRightKeyPad:
  516.                 gTank2Keys.right = isDown;
  517.                 break;
  518.             case kDownKeyPad:
  519.                 gTank2Keys.down = isDown;
  520.                 break;
  521.             case kUpKeyPad:
  522.                 gTank2Keys.up = isDown;
  523.                 break;
  524.             case kShootKeyPad:
  525.                 gTank2Keys.shoot = isDown;
  526.                 break;
  527.         }
  528.     }
  529. }
  530.  
  531.